Amplifyの提供ライブラリを使わず、他のUIライブラリで認証画面を作成してみた
こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。
Amplifyは、@aws-amplify/ui-reactを提供しているので、自分でUIを作成しなくても、簡単に認証機能、画面を実装することができます。
ただ今回は、amplifyを触るのが初めてということもあり、中身を確認するためにも、他のUIライブラリを用いて認証画面を作成してみました。
amplify authの設定
Next.jsとMantine UIを使って、実装していきます。
プロジェクトの作成
$ npx create-next-app --ts
任意のプロジェクト名を付けて、移動します。
$ cd auth-sample
amplifyの環境を作成
$ amplify init
? Initialize the project with the above configuration? No ? Enter a name for the environment dev ? Choose your default editor: Visual Studio Code ? Choose the type of app that you're building javascript Please tell us about your project ? What javascript framework are you using react ? Source Directory Path: src ? Distribution Directory Path: .next ? Build Command: npm run-script build ? Start Command: npm run-script start Using default provider awscloudformation ? Select the authentication method you want to use: AWS profile
Distribution Directory Pathの値を.nextに変更し、他の値はデフォルトにします。
profileはamplify configureで作成したものを選択してください。初めての場合は、コンソールが開きますので手順に従ってprofileの作成をします。
認証機能を追加します。
$ amplify add auth
認証構成、認証方法、詳細設定について聞かれますので、今回は以下のように設定しました。
Using service: Cognito, provided by: awscloudformation The current configured provider is Amazon Cognito. Do you want to use the default authentication and security configuration? Default configuration Warning: you will not be able to edit these selections. How do you want users to be able to sign in? Username Do you want to configure advanced settings? No, I am done. ✅ Successfully added auth resource signsampleb4cf2245 locally
設定を反映します。
$ amplify push -y
AWS Cognitoでユーザープールを確認します。amplify console
で、AWSのコンソール画面を開くことができます。
ユーザープールが作成されています。
フロントエンドの実装
amplifyをフロントエンドで使用できるよう、インストールします。
$ yarn add aws-amplify
UIライブラリのMantineをインストールします。
$ yarn add @mantine/hooks @mantine/form @mantine/core @mantine/next
import { useRouter } from "next/router"; import { FC, useEffect, useState } from "react"; import Amplify, { Auth } from "aws-amplify"; import awsconfig from "../src/aws-exports"; import { Button, Container, Group, TextInput } from "@mantine/core"; import { useForm } from "@mantine/hooks"; Amplify.configure(awsconfig); const Home: FC = () => { const router = useRouter(); const [confirm, setConfirm] = useState(false); const form = useForm({ initialValues: { username: "", email: "", password: "", code: "", }, }); useEffect(() => { router.prefetch("/profile"); const currentUser = async () => { try { const currentUser = await Auth.currentAuthenticatedUser(); if (currentUser) { router.push("/profile"); } } catch (error) { console.log(error); } }; currentUser(); }, [router]); const signUp = async (): Promise<void> => { try { await Auth.signUp({ username: form.values.username, password: form.values.password, attributes: { email: form.values.email, }, }); setConfirm(true); } catch (error) { throw new Error(); } }; const confirmSignUp = async (): Promise<void> => { const password = form.values.password; const code = form.values.code; try { await Auth.confirmSignUp(form.values.username, code); await Auth.signIn({ username: form.values.username, password: password }); router.push("/profile"); } catch (error) { throw new Error(); } }; return ( <Container style={{ width: 400, height: 200 }}> <h2> SignUp</h2> {!confirm ? ( <form onSubmit={form.onSubmit(signUp)}> <TextInput required label="username" placeholder="your name" {...form.getInputProps("username")} /> <TextInput required label="Email" placeholder="[email protected]" {...form.getInputProps("email")} /> <TextInput required label="Password" {...form.getInputProps("password")} /> <Group position="right" mt="md"> <Button type="submit">SignUp</Button> </Group> </form> ) : ( <form onSubmit={form.onSubmit(confirmSignUp)}> <TextInput required label="Code" {...form.getInputProps("code")} /> <Group position="right" mt="md"> <Button type="submit">Submit</Button> </Group> </form> )} </Container> ); }; export default Home;
confirmSignUpは、認証コードの一致を確認する関数になります。また、currentAuthenticatedUserでログインユーザーの情報を取得できます。
今回は記述しませんが、ログインの際には、signIn関数を使用します。
const signIn = async (): Promise<void> => { try { await Auth.signIn({ username: form.values.username, password: form.values.password }); router.push("/profile"); } catch (error) { throw new Error(); } };
簡単に、ログイン後のページも実装します。
import { useRouter } from "next/router"; import { useState, useEffect, FC } from "react"; import Amplify, { Auth } from "aws-amplify"; import { CognitoUserInterface } from "@aws-amplify/ui-components"; import awsconfig from "../src/aws-exports"; import { Button, Container, Group } from "@mantine/core"; Amplify.configure(awsconfig); const Profile: FC = () => { const router = useRouter(); const [user, setUser] = useState<CognitoUserInterface | undefined>(); useEffect(() => { const confirmUser = async () => { const currentUser = await Auth.currentAuthenticatedUser(); if (!currentUser) { router.push("/"); } setUser(currentUser); }; confirmUser(); }, [router]); const signOut = async (): Promise<void> => { try { await Auth.signOut(); } catch (error) { throw new Error(); } router.push("/"); }; return ( <Container style={{ width: 400, height: 200 }}> <h2>UserName : {user?.username}</h2> <Group position="left" mt="md"> <Button type="submit" onClick={signOut}> SignOut </Button> </Group> </Container> ); }; export default Profile;
開発環境で、機能確認をしてみます。
$ yarn dev
サインアップ画面
認証コード
サインアップ後
AWSのコンソールでも確認してみます。
ユーザーが登録されていますね。
まとめ
今回、バリデーションなどの記述はしていませんが、必要最低限の認証機能をMantine UIを使って実装することができました。 Amplifyには他にも、API、ホスティングなどの機能もあるので、今後も色々試してみたいと思います。
ではまた。